package com.linkgie.galaxyframework.module;

import javax.annotation.PreDestroy;

import com.linkgie.galaxyframework.context.HomeRegister;
import com.linkgie.galaxyframework.context.HomeContext;

/**
 * ModuleFactory 是一个提供者接口（SPI），用于定义模块；
 * 
 * <p>
 * 
 * 由 {@link ModuleFactory} 定义的模块由模块管理器管理，并在应用上下文初始化之前进行加载和初始化，按照以下顺序执行：<br>
 * 
 * 1. 模块管理器调用 {@link #getHomeConfiguration()}
 * 方法取得模块定义的主目录配置，并将该主目录配置混入到应用程序的主目录配置中；
 * 
 * 2. 模块管理器在完成了初始化应用程序的主目录配置之后，调用 {@link #createModule(HomeContext)} 方法初始化模块；
 * 
 * 3. 模块管理器检查 {@link #createModule(HomeContext)} 方法返回的模块对象 {@link Module} 是否实现了
 * {@link ApplicationContextInitializer} 接口， <br>
 * 如果实现了该接口，则将其注册到应用上下文中，使得在应用上下文初始化时以{@link ApplicationContextInitializer}
 * 接口回调该模块对象；实现者通过这一机制可以在最早的时机将 Bean 注入到应用上下文；
 * 
 * 4. 模块管理器注册应用退出钩子(采用 {@link Runtime#addShutdownHook(Thread)}
 * 方法)，在应用退出时调用模块对象的关闭方法 {@link Module#close()}通知模块执行清理操作；<br>
 * 这是由 JVM 负责调度执行的，执行的时机与应用上下文（{@link ApplicationContext}）本身的退出过程是并行的。<p>
 * 
 * 对实现者而言，实现退出清理操作的机制有3种选择：<br>
 * （1）通过注册监听器响应 {@link ApplicationContext} 的退出事件;
 * （2）通过标注 {@link PreDestroy} 响应 Bean 的生命周期的销毁事件，<br>
 * （3）通过实现模块的 {@link Module#close()} 方法响应退出事件。
 * 
 * @author spring
 *
 */
public interface ModuleFactory extends HomeRegister{


	/**
	 * 创建模块；
	 * 
	 * @param home 应用的主目录配置对象；
	 *             <p>
	 *             参数传入的是一个代理对象，该对象实现了所有模块以及系统定义的主目录配置的接口，也包括当前模块
	 *             {@link #getHomeConfiguration()} 方法定义的配置接口。<br>
	 *             因此实现此方法时，实现者可以根据需要对此代理对象进行类型检查并进行强制类型转换以获得所需类型的主目录配置对象；
	 * @return
	 */
	Module createModule(HomeContext home);

}
